package com.softmarket.login;

import java.io.UnsupportedEncodingException;
import java.net.CookieHandler;
import java.net.CookiePolicy;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

import org.seasar.framework.util.ResourceUtil;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

public abstract class RakutenLoginNew {

	private static String ENCODING = "UTF-8";

	// private static String START_TIME = "2013/05/13 00:00:00"; // 1368370800
	private static String START_TIME = ResourceUtil.getProperties(
			"softmarket.properties").getProperty("rakuten.service.starttime");

	// private static String END_TIME = "2014/05/13 00:00:00"; // 1399906800
	private static String END_TIME = ResourceUtil.getProperties(
			"softmarket.properties").getProperty("rakuten.service.endtime");

	private static SimpleDateFormat sf = new SimpleDateFormat(
			"yyyy/MM/dd HH:mm:ss");

	private static final String DEFAULT_DES_KEY = "B3DAC5B7B3F4BCB0B2F1BCD2";

	private static byte IV[] = { 7, 119, -127, -84, 78, -56, -18, -112 };

	private static IvParameterSpec IV_PARAM = new IvParameterSpec(IV);

	public abstract String getCheckKey();

	public abstract String getLoginUrl();

	public abstract String getLoginUrlJsession();

	public void doLogin(String shopId) {
		CorrectedCookieManager manager = new CorrectedCookieManager();
		manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
		CookieHandler.setDefault(manager);

		HttpURLConnection rmsLoginConnection = null;
		try {
			doLogin0(shopId);

			URL rmsLoginUrl = new URL(getLoginUrl(shopId));
			rmsLoginConnection = (HttpURLConnection) rmsLoginUrl
					.openConnection();
			rmsLoginConnection.setRequestProperty("Cookie", "shop="
					+ getCookieShop(shopId));
			rmsLoginConnection.connect();
			rmsLoginConnection.getHeaderField("Set-Cookie");

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (rmsLoginConnection != null) {
				rmsLoginConnection.disconnect();
			}
		}
	}

	private void doLogin0(String shopId) {
		HttpURLConnection rmsLoginConnection = null;
		try {
			URL rmsLoginUrl = new URL(getLoginUrlJsession() + shopId);
			rmsLoginConnection = (HttpURLConnection) rmsLoginUrl
					.openConnection();
			rmsLoginConnection.connect();
			rmsLoginConnection.getHeaderField("Set-Cookie");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (rmsLoginConnection != null) {
				rmsLoginConnection.disconnect();
			}
		}

	}

	public String getLoginUrl(String shopId) {
		return getLoginUrl() + "r=" + getRkey(shopId) + "&t=" + getTkey();
	}

	public String getCookieShop(String shopId) {
		// 277170&1&1368416790&1368475199
		String cookie = "";
		try {
			String min = "" + sf.parse(START_TIME).getTime() / 1000;
			String max = "" + sf.parse(END_TIME).getTime() / 1000;
			// String min = "1368416790";
			// String max ="1368475199";
			cookie = Base64.encode(shopId.concat("&").concat("1").concat("&")
					.concat(min).concat("&").concat(max).getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return cookie;
	}

	private String getCooikeRitem(String shopId) {
		// 277170&d7e03158
		String cookieValue = shopId + '&' + getRkey(shopId);
		cookieValue = new String(Base64.encode(cookieValue.getBytes()));
		try {
			cookieValue = URLEncoder.encode(cookieValue, ENCODING);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		cookieValue = encryptString(cookieValue);

		return cookieValue;
	}

	private String getRkey(String shopId) {
		return encodeMD5(getCheckKey() + getCookieShop(shopId));
	}

	private String getTkey() {
		String tkey = "";

		try {
			String min = "" + sf.parse(START_TIME).getTime() / 1000;
			String max = "" + sf.parse(END_TIME).getTime() / 1000;
			String alterKey = encodeMD5(getCheckKey() + min + max);
			tkey = URLEncoder.encode(Base64.encode(min.concat("&").concat(max)
					.concat("&").concat(alterKey).getBytes()), ENCODING);
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return tkey;
	}

	/**
	 * 指定された文字列を MD5 かけて上位８桁分の文字数を返す
	 */
	private String encodeMD5(String value) {
		String newRKey = "";
		try {
			// アルゴリズムにMD5をセット
			MessageDigest md = MessageDigest.getInstance("MD5");
			// 改竄防止キーをMD5する
			newRKey = byteToHexStr(md.digest((value).getBytes()));
			newRKey = newRKey.substring(0, 8); // 上位八文字のみ取得

		} catch (Exception e) {
			e.printStackTrace();
		}
		return newRKey;
	}

	private String byteToHexStr(byte abyte0[]) {

		StringBuffer stringbuffer = new StringBuffer();
		for (int i = 0; i < abyte0.length; i++) {
			stringbuffer.append(Character.forDigit(abyte0[i] >> 4 & 15, 16));
			stringbuffer.append(Character.forDigit(abyte0[i] & 15, 16));
		}
		return stringbuffer.toString();
	}

	public String decryptString(String s) {

		SecretKeyFactory secretkeyfactory = null;
		SecretKey secretkey = null;
		byte abyte0[] = null;
		Cipher cipher = null;

		byte abyte1[] = Base64.decode(s);

		try {
			secretkeyfactory = SecretKeyFactory.getInstance("TripleDES",
					"SunJCE");
			secretkey = secretkeyfactory.generateSecret(new DESedeKeySpec(
					DEFAULT_DES_KEY.getBytes()));

			cipher = Cipher.getInstance("TripleDES/CFB/PKCS5Padding", "SunJCE");/* 178 */
			cipher.init(2, secretkey, IV_PARAM);

			abyte0 = cipher.doFinal(abyte1);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return new String(abyte0);
	}

	public String encryptString(String s) {

		SecretKeyFactory secretkeyfactory = null;
		SecretKey secretkey = null;
		Cipher cipher = null;
		String en = "";

		try {
			secretkeyfactory = SecretKeyFactory.getInstance("TripleDES",
					"SunJCE");
			secretkey = secretkeyfactory.generateSecret(new DESedeKeySpec(
					DEFAULT_DES_KEY.getBytes()));
			cipher = Cipher.getInstance("TripleDES/CFB/PKCS5Padding", "SunJCE");
			cipher.init(1, secretkey, IV_PARAM);
			byte abyte0[];
			abyte0 = cipher.doFinal(s.getBytes());
			en = Base64.encode(abyte0);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return en;
	}
}
